﻿#include "fileservice.h"

FileService::FileService()
{
    HMODULE hNtdll =GetModuleHandleA("ntdll.dll");
    //获取文件句柄
    NtOpenFile =  (NtOpenFileDef)::GetProcAddress(hNtdll,"NtOpenFile"); //NtOpenFile
    RtlDosPathNameToNtPathName_U = (RtlDosPathNameToNtPathName_UDef)::GetProcAddress(hNtdll,"RtlDosPathNameToNtPathName_U"); //RtlDosPathNameToNtPathName_U

}

NTSTATUS FileService::NtOpenFileImpl(QString qStringFilePath, PHANDLE phFile)
{
    OBJECT_ATTRIBUTES FileObjectAttributes;
    IO_STATUS_BLOCK  IoStatusBlock;
    UNICODE_STRING usDllName;
    this->RtlDosPathNameToNtPathName_U(
                qStringFilePath.toStdWString().c_str(),
                &usDllName,
                NULL,
                NULL
                );
    //初始化对象属性结构体
    InitializeObjectAttributes(
                &FileObjectAttributes,
                &usDllName,
                OBJ_CASE_INSENSITIVE,
                NULL, NULL
                );
    //打开映射的DLL文件句柄
    return this->NtOpenFile(
                phFile
                , GENERIC_EXECUTE
                , &FileObjectAttributes
                , &IoStatusBlock
                , FILE_SHARE_READ
                , 0
                );

}


//获取文件句柄
bool FileService::CreateFileImpl(QString qStringFilePath, PHANDLE pFile)
{
    HANDLE hFile= INVALID_HANDLE_VALUE;
    hFile = CreateFile(qStringFilePath.toStdWString().c_str(),                // name of the write
                       GENERIC_READ,          // open for writing
                       FILE_SHARE_READ,        // do not share
                       NULL,                   // default security
                       OPEN_EXISTING,          // overwrite existing
                       FILE_ATTRIBUTE_NORMAL,  // normal file
                       NULL);                  // no attr. template
    if (hFile == INVALID_HANDLE_VALUE)
    {
        qDebug()<<"Could not open file (error )"<< GetLastError();
        return false;
    }
    *pFile = hFile;
    return true;
}




HANDLE MemoryAlloc(ULONG dwAllocSize, PVOID* lpReadBuffer)
{
    //创建堆的句柄对象
    HANDLE hHeap = HeapCreate(HEAP_NO_SERIALIZE, dwAllocSize, 0);
    //堆内存申请为文件的大小
    LPVOID ReadBuffer = HeapAlloc(hHeap, HEAP_NO_SERIALIZE, dwAllocSize);
    if (NULL == ReadBuffer)
    {
        qDebug()<<"HeapAlloc Fail (error:)"<< GetLastError();
    }
    else
    {
        *lpReadBuffer = ReadBuffer;
    }
    return hHeap;
}

/**
 * 获取目标文件运行平台
 * @brief FileService::GetFilePlatFormMachine
 * @param lpFileName:文件路径
 * @return: 返回目标运行平台为多少位(32或是64)
 */
DisassembleMode FileService::GetFilePlatFormMachine(LPCWSTR lpFileName)
{
    PVOID hModuleOfFileView=NULL;
    DisassembleMode model=Mode64;
    bool IsOk = this->LoadFileToHeapBuffer(lpFileName,&hModuleOfFileView);
    if (IsOk && hModuleOfFileView)
    {
        PeStruct peStruct;
        //解析PE头
        this->LoadImageHeader(hModuleOfFileView, &peStruct);
        WORD machine = peStruct.ntHeader->FileHeader.Machine;
        //目标进程为32位进程
        if (machine==IMAGE_FILE_MACHINE_I386)
        {
            model = Mode32;
        }else if (
                  machine==IMAGE_FILE_MACHINE_AMD64
                  || machine==IMAGE_FILE_MACHINE_IA64
                  || machine==IMAGE_FILE_MACHINE_AXP64
                  )
        {
            model = Mode64;
        }else {
            qDebug()<<"未知的DLL类型:(MACHINE["<<machine<<"])";
        }
        SafeFree(hModuleOfFileView);
    }
    return model;
}









//获取文件入口点
bool FileService::GetFileEntryPoint(LPCWSTR lpFileName, PULONG pEntryPoint)
{
    PeStruct peStruct;
    PVOID hModuleOfFileView;
    bool loadOk = this->LoadFileToHeapBuffer(lpFileName,&hModuleOfFileView);
    if (loadOk) {
        //解析PE头
        this->LoadImageHeader(hModuleOfFileView, &peStruct);
        ULONG entryPoint = peStruct.u.OptionalHeader->AddressOfEntryPoint;
        *pEntryPoint = entryPoint;
        //模块入口
        SafeFree(hModuleOfFileView);
        return true;
    }
    return false;
}





QString FileService::GetFileInformation(QString qStringFilePath, enum FileInformation enumInformationCode)
{
    struct LANGANDCODEPAGE {
        WORD wLanguage;
        WORD wCodePage;
    } *lpTranslate;
    QString retnInformation;

    if (qStringFilePath.isEmpty())
    {
        return retnInformation;
    }
    //转换QString路径为wchar_t*
    ULONG dwHandle=0;
    //获取文件版本信息缓冲区大小
    ULONG infoSize=GetFileVersionInfoSize(qStringFilePath.toStdWString().c_str(),&dwHandle);
    if (infoSize) {
        wchar_t* pBlock = new wchar_t[infoSize];
        if ( GetFileVersionInfo(qStringFilePath.toStdWString().c_str(),0,infoSize,pBlock))
        {
            // Read the list of languages and code pages.
            uint cbTranslate;
            if (VerQueryValue(pBlock,TEXT("\\VarFileInfo\\Translation"),(LPVOID*)&lpTranslate,&cbTranslate))
            {
                PVOID lpBuffer;
                uint uLength;
                std::wstring formats;
                //LegalCopyright:版权信息
                //CompanyName:公司名称
                //ProductVersion:产品版本
                //ProductName:产品名称
                QString stringFileInfo = QString("\\StringFileInfo\\%1%2\\%3")
                        .arg(lpTranslate->wLanguage,4,16, QChar('0'))
                        .arg(lpTranslate->wCodePage,4,16, QChar('0'));
                switch (enumInformationCode) {

                case Comments:
                    formats = stringFileInfo.arg("Comments").toStdWString();
                    break;
                case InternalName:
                    formats = stringFileInfo.arg("InternalName").toStdWString();
                    break;
                case ProductName:
                    formats = stringFileInfo.arg("ProductName").toStdWString();
                    break;
                case CompanyName:
                    formats = stringFileInfo.arg("CompanyName").toStdWString();
                    break;
                case ProductVersion:
                    formats = stringFileInfo.arg("ProductVersion").toStdWString();
                    break;
                case LegalCopyright:
                    formats = stringFileInfo.arg("LegalCopyright").toStdWString();
                    break;
                case FileDescription:
                    formats = stringFileInfo.arg("FileDescription").toStdWString();
                    break;
                case   LegalTrademarks   :
                    formats = stringFileInfo.arg("LegalTrademarks").toStdWString();
                    break;
                case   PrivateBuild      :
                    formats = stringFileInfo.arg("PrivateBuild").toStdWString();
                    break;
                case   FileVersion       :
                    formats = stringFileInfo.arg("FileVersion").toStdWString();
                    break;
                case   OriginalFilename  :
                    formats = stringFileInfo.arg("OriginalFilename").toStdWString();
                    break;
                case   SpecialBuild      :
                    formats = stringFileInfo.arg("SpecialBuild").toStdWString();
                    break;
                default:
                    break;
                }
                const wchar_t* subInfoString =  formats.c_str();
                if (VerQueryValue((LPCVOID)pBlock,subInfoString,&lpBuffer, &uLength))
                {
                    retnInformation = QString::fromWCharArray(static_cast<LPWSTR>(lpBuffer));
                    SafeDelete(pBlock);
                    return retnInformation;
                }
            }
        }
    }
    return retnInformation;
}










/*
    加载文件到内存
*/
bool FileService::LoadFileToHeapBuffer(LPCWSTR lpFileName, OUT PVOID* lpFileBuffer)
{
    HANDLE hFile = CreateFileW(lpFileName, // file to open
                               GENERIC_READ,          // open for reading
                               FILE_SHARE_READ,       // share for reading
                               NULL,                  // default security
                               OPEN_EXISTING,         // existing file only
                               FILE_ATTRIBUTE_NORMAL, // normal file
                               NULL);                 // no attr. template

    if (hFile == INVALID_HANDLE_VALUE)
    {
        qDebug()<<"Could not open file (error)"<< GetLastError();
        return false;
    }
    DWORD dwSizeLow = GetFileSize(hFile, NULL);

    if (dwSizeLow == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
        qDebug()<<"Could not read file size (error :)"<< GetLastError();
        CloseHandle(hFile);
        return false;
    }

    //实际读取字节数
    DWORD dwBytesRead = 0;
    //申请文件大小的内存
    LPVOID ReadBuffer = malloc(dwSizeLow);
    //读取文件到缓冲区ReadBuffer,读取大小dwSizeLow
    if (FALSE == ReadFile(hFile, ReadBuffer, dwSizeLow, &dwBytesRead, NULL))
    {
        qDebug()<<"Could not read from file:"<<lpFileName<<"error:"<<GetLastError();
        CloseHandle(hFile);
        SafeFree(ReadBuffer);
        return false;
    }
    if (dwBytesRead > 0)
    {
        //        qDebug()<<"Text read from"<<QString::fromWCharArray(lpFileName) <<dwBytesRead<< "bytes";
        *lpFileBuffer = ReadBuffer;
    }
    else
    {
        qDebug()<<("No data read from file")<<QString::fromWCharArray(lpFileName);
    }
    CloseHandle(hFile);
    return true;
}

void FileService::LoadImageHeader(PVOID hModule, PPeStruct pPeStruct)
{
    //初始化PE头指针
    pPeStruct->dosHeader = (PIMAGE_DOS_HEADER)hModule;
    //[偏移量:0x3C] [PE文件头地址.]
    pPeStruct->ntHeader = (PIMAGE_NT_HEADERS)((PUCHAR)hModule + pPeStruct->dosHeader->e_lfanew);
    pPeStruct->FileHeader = &(pPeStruct->ntHeader->FileHeader);
    pPeStruct->u.OptionalHeader = &(pPeStruct->ntHeader->OptionalHeader);
    //x86 和 x64 OptionalHeader的大小不相同,使用SizeOfOptionalHeader来确定大小
    PUCHAR sect = (PUCHAR)pPeStruct->FileHeader + sizeof(IMAGE_FILE_HEADER) + pPeStruct->FileHeader->SizeOfOptionalHeader;
    pPeStruct->SectionHeader = (PIMAGE_SECTION_HEADER)sect;
}
/*
    转换文件映像为内存映像
    imageSectionHeader.PointerToRawData：文件中相对偏移位置
    imageSectionHeader.VirtualAddress:内存镜像中的相对偏移位置
    imageSectionHeader.SizeOfRawData:文件中节的尺寸（字节）
*/
VOID FileService::MapFileViewToImageView(PULONG_PTR hModuleOfImageView, IN PVOID hModuleOfFileView)
{
    //PE头结构体
    PeStruct peStruct;
    //解析PE头
    this->LoadImageHeader(hModuleOfFileView, &peStruct);

    PVOID hModuleImageBuffer = VirtualAlloc(NULL, peStruct.u.OptionalHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    //内存镜像映射完成后,设置出参中的指针指向内存镜像
    *hModuleOfImageView = (ULONG_PTR)hModuleImageBuffer;
    //拷贝Headers
    memcpy(hModuleImageBuffer, hModuleOfFileView, peStruct.u.OptionalHeader->SizeOfHeaders);
    //拷贝Section
    for (size_t i = 0; i < peStruct.FileHeader->NumberOfSections; i++)
    {
        IMAGE_SECTION_HEADER imageSectionHeader = peStruct.SectionHeader[i];
        memcpy((PUCHAR)hModuleImageBuffer + imageSectionHeader.VirtualAddress, (PUCHAR)hModuleOfFileView + imageSectionHeader.PointerToRawData, imageSectionHeader.SizeOfRawData);
    }
    SafeFree(hModuleOfFileView);
    //返回申请的堆句柄
    return;
}

/*
遍历导出表
导出符号指：导出的函数或变量等
*/
void FileService::IterExportTable(PIMAGE_DATA_DIRECTORY pDataDirectory,ULONG64 hModuleOfImageView)
{
    ULONG exportTableVa = pDataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    if (exportTableVa)
    {
        PIMAGE_EXPORT_DIRECTORY pImageExport = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)hModuleOfImageView + exportTableVa);

        qDebug()<< "NumberOfFunctions:"<<pImageExport->NumberOfFunctions
                <<"NumberOfNames:"<< pImageExport->NumberOfNames;
        //符号导出序号的Base，(Base + AddressOfNameOrdinals的值 = 导出序号)
        ULONG OriginBase = pImageExport->Base;
        for (size_t i = 0, originIndex = 0; i < pImageExport->NumberOfFunctions; i++)
        {
            //如果地址表中存在0x0的地址,则序号表中可能存在不连续的序号(导致地址表长度大于实际导出符号数量,跳过本次遍历)
            if (((PULONG_PTR)(pImageExport->AddressOfFunctions + hModuleOfImageView))[i])
            {
                //符号名称表:PImageExport->AddressOfNames 宽度4字节
                //名称表的下标对应序号表的下标,序号表中的值对应地址表的下标
                ULONG_PTR symbolName = hModuleOfImageView + ((PULONG_PTR)(pImageExport->AddressOfNames + hModuleOfImageView))[originIndex];
                //符号序号表:PImageExport->AddressOfNameOrdinals 宽度2字节
                ULONG_PTR symbolOrigin = ((PUSHORT)(hModuleOfImageView + pImageExport->AddressOfNameOrdinals))[originIndex];
                //符号地址表:PImageExport->AddressOfFunctions 宽度4字节
                //符号相对虚拟地址
                ULONG_PTR symbolAddressVa = ((PULONG)(pImageExport->AddressOfFunctions + hModuleOfImageView))[symbolOrigin];
                //符号地址=hmodule+相对虚拟地址
                ULONG_PTR symbolAddress = hModuleOfImageView + symbolAddressVa;
                //导出序号 = 符号地址表的下标(序号表中的值) + Base
                qDebug()<< "符号名称:"<<QString::fromLocal8Bit((PCCHAR)symbolName)
                        << "符号地址:"<< QString("0x%1").arg(symbolAddress,8,16,QChar('0'))
                        << "导出序号:"<< QString("0x%1").arg(symbolOrigin + OriginBase);

                originIndex++;
                continue;
            }
        }
        return;
    }
    qDebug()<< "没有导出表信息！";
}




/*
    根据导出名称或序号查找导出表
*/
ULONG FileService::SearchFunctionAddressByNameOrByOrigin(
        PIMAGE_DATA_DIRECTORY pDataDirectory
        ,PCNZCH name
        ,ULONG origin
        ,SearchTypeForExportTable serchType
        ,ULONG_PTR hModuleOfImageView
        )
{
    ULONG exportTableVa = pDataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    if (exportTableVa)
    {
        PIMAGE_EXPORT_DIRECTORY pImageExport = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)hModuleOfImageView + exportTableVa);
//        qDebug()<< "NumberOfFunctions:"<<pImageExport->NumberOfFunctions
//                <<"NumberOfNames:"<< pImageExport->NumberOfNames;
        //符号导出序号的Base，(Base + AddressOfNameOrdinals的值 = 导出序号)
        ULONG OriginBase = pImageExport->Base;
        for (size_t i = 0, originIndex = 0; i < pImageExport->NumberOfFunctions; i++)
        {
            //如果地址表中存在0x0的地址,则序号表中可能存在不连续的序号(导致地址表长度大于实际符号数量,跳过本次遍历)
            if (((PULONG_PTR)(pImageExport->AddressOfFunctions + hModuleOfImageView))[i])
            {
                //按名称搜索
                if (SearchTypeForExportTable::ByName == serchType)
                {
                    //符号名称表:PImageExport->AddressOfNames 宽度4字节
                    //名称表的下标对应序号表的下标,序号表中的值对应地址表的下标
                    ULONG_PTR functionName = hModuleOfImageView + ((PULONG)(pImageExport->AddressOfNames + hModuleOfImageView))[originIndex];
                    if (strcmp((PCHAR)functionName, name) == 0)
                    {
                        //符号序号表:PImageExport->AddressOfNameOrdinals 宽度2字节
                        USHORT symbolIndex = ((PUSHORT)(hModuleOfImageView + pImageExport->AddressOfNameOrdinals))[originIndex];
                        //符号地址表:PImageExport->AddressOfFunctions 宽度4字节 (相对虚拟地址)
                        ULONG symbolAddressVa = ((PULONG)(pImageExport->AddressOfFunctions + hModuleOfImageView))[symbolIndex];
                        //导出符号地址 = hmodule+相对虚拟地址
                        //                        ULONG_PTR symbolAddress = symbolAddressVa + hModuleOfImageView;
                        //导出序号 = 符号地址表的下标(序号表中的值) + Base
                        //                        qDebug()<< "符号名称:"<<QString::fromLocal8Bit((PCNZCH)functionName)
                        //                                << "符号地址:"<< QString("0x%1").arg(symbolAddress,8,16,QChar('0'))
                        //                                << "导出序号:"<< QString("0x%1").arg(symbolIndex + OriginBase);
                        return symbolAddressVa;
                    }
                }
                //按序号搜索
                else {
                    if (origin > pImageExport->NumberOfFunctions)
                    {
                        qDebug()<< "查询的序号已经超出导出符号有效范围 - 最大有效范围"<<pImageExport->NumberOfFunctions;
                        break;
                    }
                    {
                        ULONG functionIndex = origin - OriginBase;
                        //符号地址表:PImageExport->AddressOfFunctions 宽度4字节
                        ULONG_PTR functionVirAddress = ((PULONG_PTR)(pImageExport->AddressOfFunctions + hModuleOfImageView))[functionIndex];
                        //                        ULONG_PTR functionName = 0;
                        for (size_t i = 0; i < pImageExport->NumberOfFunctions; i++)
                        {
                            //符号序号表:PImageExport->AddressOfNameOrdinals 宽度2字节
                            //                            USHORT functionOrigin = ((PUSHORT)(hModuleOfImageView + pImageExport->AddressOfNameOrdinals))[i];
                            //                            if (functionOrigin == functionIndex)
                            //                            {
                            //                                //名称表的下标对应序号表的下标,序号表中的值对应地址表的下标
                            //                                functionName = hModuleOfImageView + ((PULONG_PTR)(pImageExport->AddressOfNames + hModuleOfImageView))[i];
                            //                            }

                        }
                        //                        //导出序号 = 符号地址表的下标(序号表中的值) + Base
                        //                        qDebug()<< "符号名称:"<<QString::fromLocal8Bit((PCNZCH)functionName)
                        //                                << "符号地址:"<< QString("0x%1").arg(functionVirAddress + hModuleOfImageView,8,16,QChar('0'))
                        //                                << "导出序号:"<< QString("0x%1").arg(functionIndex + OriginBase);
                        return functionVirAddress + hModuleOfImageView;
                    }
                }
                originIndex++;
                continue;
            }
        }
        qDebug()<< "没有搜索到相关导出信息";
    }
    else
    {
        qDebug()<< "没有导出表信息！";
    }
    return -1;
}





